package cn.lei.netty.herostory;

import cn.lei.netty.herostory.cmdhandler.CmdHandlerFactory;
import cn.lei.netty.herostory.cmdhandler.ICmdHandler;
import com.google.protobuf.GeneratedMessageV3;
import io.netty.channel.ChannelHandlerContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author lei
 */
public class MainMsgProcessor {
    /**
     * 日志对象
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(MainMsgProcessor.class);

    /**
     * 单例对象
     */
    private static final MainMsgProcessor INSTANCE = new MainMsgProcessor();

    /**
     * 私有化构造器
     */
    private MainMsgProcessor() {

    }

    /**
     * 获取单例对象
     *
     * @return
     */
    public static MainMsgProcessor getInstance() {
        return INSTANCE;
    }

    /**
     * 创建一个单线程的线程池
     */
    private final ExecutorService es = Executors.newSingleThreadExecutor((newRunnable) -> {
        Thread thread = new Thread(newRunnable);
        thread.setName("MainMsgProcessor");
        return thread;
    });

    /**
     * 处理消息
     *
     * @param ctx
     * @param msg
     */
    public void process(ChannelHandlerContext ctx, Object msg) {

        final Class<?> msgClazz = msg.getClass();

        LOGGER.info("收到客户端消息, msgClazz = {}, msgBody = {}", msg.getClass().getSimpleName(), msg);

        if (ctx == null || msg == null) {
            return;
        }

        es.submit(() -> {
            try {
                //获取命令处理器
                ICmdHandler<? extends GeneratedMessageV3> cmdHandler = CmdHandlerFactory.create(msgClazz);
                if (cmdHandler != null) {
                    cmdHandler.handle(ctx, cast(msg));
                }
            } catch (Exception ex) {
                //记录错误日志
                LOGGER.error(ex.getMessage(), ex);
            }
        });

    }

    /**
     * 处理runnable实例
     *
     * @param r
     */
    public void process(Runnable r) {
        if (r == null) {
            return;
        }
        es.submit(r);
    }

    /**
     * 转型为命令对象
     *
     * @param msg    消息对象
     * @param <TCmd> 消息类
     * @return 命令对象
     */
    private static <TCmd extends GeneratedMessageV3> TCmd cast(Object msg) {
        if (msg == null) {
            return null;
        } else {
            return (TCmd) msg;
        }
    }


}
